
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 定义 sigmoid 函数
def sigmoid(x):
    return 1/(1+np.exp(-x))

# 读取数据集
data_tr = pd.read_csv(r'BPdata_tr.txt')
data_te = pd.read_csv(r'BPdata_te.txt')

n = len(data_tr)
yita = 0.85

out_in = np.array([0.0, 0, 0, 0, -1])
w_mid = np.zeros([3, 4])
w_out = np.zeros([5])
delta_w_out = np.zeros([5])
delta_w_mid = np.zeros([3,4])
Err = []

for j in range(100):
    error = []
    for it in range(n):
        net_in = np.array([data_tr.iloc[it,0],data_tr.iloc[it,1],-1])
        real = data_tr.iloc[it,2]

        for i in range(4):
            out_in[i] = sigmoid(sum(net_in * w_mid[:, i]))

        res = sigmoid(sum(out_in * w_out))
        error.append(abs(real-res))

        delta_w_out = yita * res * (1 - res) * (real - res) * out_in
        delta_w_out[4] = -yita * res * (1 - res) * (real - res)
        w_out = w_out + delta_w_out

        for i in range(4):
            delta_w_mid[:,i] = yita * out_in[i] * (1 - out_in[i]) * w_out[i] * res * (1 - res) * (real - res) * net_in
            delta_w_mid[2,i] = -yita * out_in[i] * (1 - out_in[i]) * w_out[i] * res * (1 - res) * (real - res)
            w_mid = w_mid + delta_w_mid

    Err.append(np.mean(error))

plt.plot(Err)
plt.show()

error_te = []
for it in range(len(data_te)):
    net_in = np.array([data_te.iloc[it,0],data_te.iloc[it,1],-1])
    real = data_te.iloc[it,2]
    for i in range(4):
        out_in[i] = sigmoid(sum(net_in * w_mid[:, i]))
    res = sigmoid(sum(out_in * w_out))
    error_te.append(abs(real-res))

plt.plot(error_te)
plt.show()
print(np.mean(error_te))

# scikit-learn implementation
from sklearn.neural_network import MLPRegressor

model = MLPRegressor(hidden_layer_sizes=(10,), random_state=10, max_iter=800, learning_rate_init=0.1)
model.fit(data_tr.iloc[:, :2], data_tr.iloc[:, 2])
pre = model.predict(data_te.iloc[:, :2])

err = np.abs(pre - data_te.iloc[:, 2]).mean()
print(err)

plt.plot(model.loss_curve_)
plt.title('Model Loss Curve')
plt.xlabel('Iteration')
plt.ylabel('Loss')
plt.show()


